<?php
declare (strict_types=1);

namespace app\exam\logic\admin;

use app\admin\logic\system\Log;
use app\common\event\subscribes\attach\Attach as AttachSubscribes;
use app\common\exception\LogicException;
use app\common\library\Excel;
use app\common\logic\Attach;
use app\exam\model\admin\PaperStudent as PaperStudentModel;
use app\user\logic\user\admin\Account;
use Exception;
use think\db\exception\DataNotFoundException;
use think\db\exception\DbException;
use think\db\exception\ModelNotFoundException;
use think\facade\Event;
use think\facade\Request;
use think\Paginator;

/**
 * 派发考试
 */
class PaperStudent extends PaperStudentModel
{
    /**
     * 获取列表
     *
     * @param array $map
     * @return Paginator
     * @throws DbException
     */
    public function getList(array $map = []): Paginator
    {
        return $this->with(['user'])->where($map)->order('create_time', 'DESC')->paginate($this->getListRows());
    }

    /**
     * created
     *
     * @param array $data
     * @return bool
     * @throws DbException
     * @throws DataNotFoundException
     * @throws ModelNotFoundException
     */
    public function created(array $data): bool
    {
        // 验证数据
        $this->getValidate()->scene('create')->failException()->check($data);

        $user = app(Account::class)->where('phone', $data['phone'])->find();
        if (!$user) {
            throw new LogicException('所发放用户不存在');
        }

        $userId = $user->id;

        $student = $this->where(['mhm_id' => request()->mhm_id, 'user_id' => $userId, 'paper_id' => $data['paper_id']])->findOrEmpty();
        if (!$student->isEmpty()) {
            throw new LogicException('所发放用户已存在，无需重复发放');
        }
        // 用户数据
        $saved = [
            'mhm_id'            => request()->mhm_id,
            'paper_id'          => $data['paper_id'],
            'user_id'           => $userId,
            'exam_stime'        => $data['time'] ? $data['time'][0] : null,
            'exam_etime'        => $data['time'] ? $data['time'][1] : null,
            'exam_score_pass'   => $data['exam_score_pass'] ?? 0.0,
            'face_verification' => $data['face_verification'] ?? 0,
            'exam_number'       => $data['exam_number'] ?? 0
        ];

        // 创建成功
        if (!$this->create($saved)) {
            throw new LogicException('发放失败');
        }

        // Log::write('新建派发考试【' . $data['title'] . '】', 'exam_paper_student', 'create', true);

        return true;
    }

    /**
     * deletes
     *
     * @param $ids
     */
    public function deletes($ids)
    {
        $res = $this->whereIn('id', $ids)->delete();

        if (!$res) {
            throw new LogicException("移除失败");
        }

        // Log::write('删除派发考试【' . $res->title . '】', 'exam_paper_student', 'delete', true);
    }

    /**
     * 导入学员
     * Author   Martinsun<syh@sunyonghong.com>
     * Date 2020-08-10
     *
     * @param int   $paperId
     * @param int   $attachId
     * @param array $config
     * @return array [type]                                    [description]
     * @throws Exception
     */
    public function doImportStudent(int $paperId, int $attachId, array $config): array
    {
        // 试卷信息
        $paper = app(Paper::class)->findOrEmpty($paperId);
        if ($paper->isEmpty()) throw new LogicException('试卷数据错误');
        // 获取附件信息
        $attach = app(Attach::class)->where('id', $attachId)->findOrEmpty();
        if ($attach->isEmpty()) throw new LogicException('附件不存在，请重新上传');
        //
        $filepath = $attach->filepath;
        if (!is_file($filepath)) throw new LogicException('附件不存在，请重新上传');
        // 加载附件内容
        $data = Excel::import($filepath);
        unset($data[0]);
        // 导入数据的数量
        $importCount = count($data);
        // 单次最多导入1000条数据
        if ($importCount > 1000) throw new LogicException('单次最多导入1000条数据');
        //
        $data  = array_column($data, '1');
        $datas = array_chunk($data, 200);
        $total = 0;
        $error = [];
        $users = [];
        // 检查数据是否正确,超过10条错误数据,则不允许导入
        foreach ($datas as $phones) {
            $exits = app(Account::class)->whereIn('phone', $phones)->column('phone', 'id');
            $users += $exits;
            $diff  = array_diff($phones, $exits);
            $count = count($diff);
            if ($count > 0) {
                $error = $error + $diff;
            }
            $total += $count;

            if ($total >= 10) {
                break;
            }

        }

        if ($total > 0) {
            $error = array_slice($error, 0, 10);
            $txt   = $total > 10 ? '等' : '';
            // 有错误
            throw new LogicException('手机号【' . implode('，', $error) . '】' . $txt . '用户不存在，请先创建用户或检查导入数据');
        }
        // 批量添加
        $inserts = [];
        $time    = Request::time();
        foreach ($users as $userId => $phone) {
            $id = $this->where(['mhm_id' => request()->mhm_id, 'user_id' => $userId, 'paper_id' => $paperId])->value('id');
            if ($id) {
                continue;
            }
            $add = [
                'mhm_id'            => request()->mhm_id,
                'paper_id'          => $paperId,
                'user_id'           => $userId,
                'exam_stime'        => $config['time'] ? $config['time'][0] : null,
                'exam_etime'        => $config['time'] ? $config['time'][1] : null,
                'exam_number'       => $config['exam_number'] ?? 0,
                'exam_score_pass'   => $config['exam_score_pass'] ?? 0.0,
                'face_verification' => $config['face_verification'] ?? 0,
                'create_time'       => $time,
                'update_time'       => $time
            ];
            // if (!$student->isEmpty()) {
            //     $add['id'] = $student->id;
            // }
            $inserts[] = $add;
        }

        if (empty($inserts)) {
            // 删除附件
            Event::subscribe(AttachSubscribes::class);
            Event::trigger('AttachTrueDeleted', $attachId);

            throw new LogicException("无新的学员导入，请检查是否重复导入");
        }
        // $max     = $this->max('id');
        // $success = $this->extra('IGNORE')->insertAll($inserts, 250);
        $success      = $this->saveAll($inserts);
        $successCount = count($success);
        if ($successCount == 0) {
            // 删除附件
            Event::subscribe(AttachSubscribes::class);
            Event::trigger('AttachTrueDeleted', $attachId);

            throw new LogicException("导入失败，请检查是否重复导入");
        }

        // $users = $this->where('id', '>', $max)->limit($success)->column('user_id');

        Log::write('导入附件【' . $attach->filename . '】中的学员到试卷【' . $paper->title . '】', 'paper_student', 'create', true);

        // 删除附件
        Event::subscribe(AttachSubscribes::class);
        Event::trigger('AttachTrueDeleted', $attachId);

        return [
            'total'   => $importCount,
            'success' => $successCount,
            'exists'  => $importCount - $successCount,
        ];
    }

    /**
     * 获取用户指派考试列表
     * Author 亓官雨树<lucky.max@foxmail.com>
     * Date 2023-07-07
     *
     * @param array $param [description]
     * @return mixed [type]        [description]
     */
    public function getPaperStudentList(array $param)
    {
        // 参数
        $mid = request()->mid;
        // $mhm_id = request()->mhm_id;

        // 数据
        // 购买的考试
        // $order_paper = app(PaymentOrder::class)->alias('o')->Join('payment_order_item i', "i.order_no=o.order_no AND i.product_type_id IN (8,9,10) AND i.user_id=$mid AND i.mhm_id=$mhm_id AND o.status=20")->group('i.user_id,i.product_id')->column('i.product_id');

        // 指派的考试
        $student_paper = $this->where('user_id', $mid)->where('type', 1)->order('create_time', 'DESC')->paginate($this->getListRows())->each(function ($i) {
            if ($i->order_type == 8) {
                $i->paper = app(ModuleExamination::class)->where('id', $i->paper_id)->with(['paper'])->findOrEmpty();
            } else if ($i->order_type == 9) {
                $i->paper = app(ModuleSpecialTopic::class)->where('id', $i->paper_id)->with(['paper'])->findOrEmpty();
            } else if ($i->order_type == 10) {
                $i->paper = app(ModuleRollupPaper::class)->where('id', $i->paper_id)->with(['paper'])->findOrEmpty();
            }
        });

        // 整合数据
        // $all_paper = array_merge($order_paper,$student_paper);

        $empty = new \ArrayObject();
        if ($student_paper->isEmpty()) return $empty;

        return $student_paper;
    }
}
